; Copyright 2013 padnest@gmail.com

; Licensed under the Apache License, Version 2.0 (the "License");
; you may not use this file except in compliance with the License.
; You may obtain a copy of the License at
;
;   http://www.apache.org/licenses/LICENSE-2.0
;
; Unless required by applicable law or agreed to in writing, software
; distributed under the License is distributed on an "AS IS" BASIS,
; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
; See the License for the specific language governing permissions and
; limitations under the License.


	LIST p=18F4431
	#include <p18f4431.inc>
    #include pic18f-langext-v1.0.inc

; configs
	CONFIG OSC = HS
	CONFIG IESO = OFF
	CONFIG FCMEN = OFF
	CONFIG PWRTEN = ON
	CONFIG WDTEN = OFF
	CONFIG BOREN = OFF
	CONFIG MCLRE = ON
	CONFIG LVP = OFF
	CONFIG DEBUG = OFF
	CONFIG STVREN = ON

; registers
	UDATA
Flags		res 1
Temp		res 1
DUTY0		res 1

#DEFINE Flags_Dir		Flags, 0


; reset vector
	ORG	0x0000
	goto	main

; interrupt vector in compatibility mode
	ORG	0x0008

interrupt:
	btfsc	Flags_Dir		; if set increment DUTY until 0x3FFF
	goto	int_inc
		
int_dec:
	movf    DUTY0, W        ; DUTY0 = 0 ?
    bz      int_dec_switch  ; yes: switch direction
    decf    DUTY0, F        ; no: dec DUTY0
    goto	int_exit		; exit
int_dec_switch:
    btg		Flags_Dir		; switch direction
	goto	int_exit		; and exit

int_inc:
    movlw	0xFF            ; DUTY0 = 0xFF?
    subwf   DUTY0, W
    bz      int_inc_switch  ; yes: go to switch direction
    incf    DUTY0, F        ; no: inc DUTY0
    goto	int_exit		; exit
int_inc_switch:
    btg		Flags_Dir		; switch direction

int_exit:
    movff   DUTY0, Temp     ; write DUTY0 bits 7:6 in PDC0H<1:0> using Temp register
    shftrf  Temp, 6         ; shift Temp >> 6
    movff   Temp, PDC0H     ; write PDC0H

    movff   DUTY0, Temp     ; write DUTY0 bits 5:0 in PDC0L<7:2> using Temp register
    shftlf  Temp, 2         ; shift Temp << 2
    movff   Temp, PDC0L     ; write PDC0L
   
	bcf		PIR3, PTIF
	retfie	FAST

main:

	; init registers
	clrf	Flags           ; clear all flags
	bsf		Flags_Dir		; set increment direction
    clrf    DUTY0           ; set DUTY0 initial value


	; init PWM
	movlw	b'00001000'			; event trigger postcale 1:1 + time base FOSC/64 + free-running mode
	movwf	PTCON0				; PTOPS<7:4> PTCKPS<3:2> PTMOD<1:0>
	movlw	b'00000000'			; time base off + time base count up
	movwf	PTCON1				; PTEN<7> PTDIR<6>
	movlw	b'00101111'			; PWM0&PWM1 pin enabled for out + indipendent mode for all PWM pair
	movwf	PWMCON0				; -<7> PWMEN<6:4> PMOD<3-0>
    movlw	b'00000000'			;
	movwf	PWMCON1				;

	movlw	0x00				; time base period (upper 4 bits)
	movwf	PTPERH				; -<7:4> PTPERH<3:0>
	movlw	0xFF				; time base period (lower 8 bits)
	movwf	PTPERL				; PTPERL<7:0>

	movlw	0x00				; clear duty upper 6 bits
	movwf	PDC0H				; -<7:6> PDC0H<5:0>
	movlw	0x00 				; clear duty lower 6 bits + Q1 duty cycle match
	movwf	PDC0L				; PDC0L<7:2> Q-CLOCK<1:0>

    
	; init interrupts
	bcf		RCON, IPEN			; disable high priority interrupts mode
	movlw	b'11000000'			; GIE + PEIE enabled
	movwf	INTCON				; GIE/GIEH<7> PEIE/GIEL<6> TMR0IE<5> INT0IE<4> RBIE<3> TMR0IF<2> INT0IF<1> RBIF<0>
	movlw	b'00010000'			; PWM Time Base Interrupt enabled (PTIE)
	movwf	PIE3				; -<7:5> PTIE<4> IC3DRIE<3> IC2QEIE<2> IC1IE<1> TMR5IE<0>
	clrf	PIR3				; clear all peripheral interrupt flags

go:
	bsf		PTCON1, PTEN		; time base on
	
loop8:							; infinite loop
	goto	loop8

	END